If the rather simple,
standard method for specifying how to split mail doesn't allow
you to do what you want, you can set
nnmail-split-methods to
nnmail-split-fancy. Then you can play with the
nnmail-split-fancy variable.
Let's look at an example value of this variable first:
;; Messages from the mailer daemon are not crossposted to any of
;; the ordinary groups. Warnings are put in a separate group
;; from real errors.
(| ("from" mail (| ("subject" "warn.*" "mail.warning")
"mail.misc"))
;; Non-error messages are crossposted to all relevant
;; groups, but we don't crosspost between the group for the
;; (ding) list and the group for other (ding) related mail.
(& (| (any "ding@ifi\\.uio\\.no" "ding.list")
("subject" "ding" "ding.misc"))
;; Other mailing lists...
(any "procmail@informatik\\.rwth-aachen\\.de" "procmail.list")
(any "SmartList@informatik\\.rwth-aachen\\.de" "SmartList.list")
;; Both lists below have the same suffix, so prevent
;; cross-posting to mkpkg.list of messages posted only to
;; the bugs- list, but allow cross-posting when the
;; message was really cross-posted.
(any "bugs-mypackage@somewhere" "mypkg.bugs")
(any "mypackage@somewhere" - "bugs-mypackage" "mypkg.list")
;; People...
(any "larsi@ifi\\.uio\\.no" "people.Lars_Magne_Ingebrigtsen"))
;; Unmatched mail goes to the catch all group.
"misc.misc")
This variable has the format of a split. A split is a (possibly) recursive structure where each split may contain other splits. Here are the possible split syntaxes:
group(field value
[- restrict [...] ]
split
[invert-partial])If restrict (yet another regexp) matches some string after field and before the end of the matched value, the split is ignored. If none of the restrict clauses match, split is processed.
The last element invert-partial is optional. If
it is non-nil, the match-partial-words behavior
controlled by the variable
nnmail-split-fancy-match-partial-words (see
below) is be inverted. (New in Gnus 5.10.7)
(| split ...)| (vertical bar), then process each
split until one of them matches. A split
is said to match if it will cause the mail message to be stored
in one or more groups.(& split ...)&, then process all splits in the
list.junkjunk, then don't
save (i.e., delete) this message. Use with extreme
caution.(: function arg1
arg2 ...)For instance, the following function could be used to split based on the body of the messages:
(defun split-on-body ()
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(when (re-search-forward "Some.*string" nil t)
"string.group"))))
The buffer is narrowed to the header of the message in
question when function is run. That's why
(widen) needs to be called after
save-excursion and save-restriction
in the example above. Also note that with the nnimap backend,
message bodies will not be downloaded by default. You need to
set nnimap-split-download-body to t
to do that (see
Client-Side IMAP Splitting).
(! func
split)!, then split will be processed, and
func will be called as a function with the result of
split as argument. func should return a
split.nilnil, it is ignored.In these splits, field must match a complete field name.
Normally, value in these splits must match a
complete word according to the fundamental mode syntax
table. In other words, all value's will be implicitly
surrounded by \<...\> markers, which are word
delimiters. Therefore, if you use the following split, for
example,
(any "joe" "joemail")
messages sent from ‘joedavis@foo.org’ will normally not be filed in ‘joemail’. If you want to alter this behavior, you can use any of the following three ways:
nnmail-split-fancy-match-partial-words variable
to non-nil in order to ignore word boundaries
and instead the match becomes more like a grep. This variable
controls whether partial words are matched during fancy
splitting. The default value is nil.
Note that it influences all value's in your split rules.
.* ignores
word boundaries in front of a word. Similarly, if
value ends with .*, word boundaries in
the rear of a word will be ignored. For example, the
value "@example\\.com" does not match
‘foo@example.com’ but
".*@example\\.com" does.nnmail-split-fancy-match-partial-words is
nil. Contrarily, if the flag is set, word
boundaries are not ignored even if
nnmail-split-fancy-match-partial-words is
non-nil. (New in Gnus 5.10.7)field
and value can also be Lisp symbols, in that case they
are expanded as specified by the variable
nnmail-split-abbrev-alist. This is an alist of cons
cells, where the car of a cell contains
the key, and the cdr contains the
associated value. Predefined entries in
nnmail-split-abbrev-alist include:
fromtoanyfrom and to
entries.nnmail-split-fancy-syntax-table
is the syntax table in effect when all this splitting is
performed.
If you want to have Gnus create groups dynamically based on
some information in the headers (i.e., do
replace-match-like substitutions in the group
names), you can say things like:
(any "debian-\\b\\(\\w+\\)@lists.debian.org" "mail.debian.\\1")
In this example, messages sent to ‘debian-foo@lists.debian.org’ will be filed in ‘mail.debian.foo’.
If the string contains the element ‘\&’, then the previously matched string will be substituted. Similarly, the elements ‘\\1’ up to ‘\\9’ will be substituted with the text matched by the groupings 1 through 9.
Where
nnmail-split-lowercase-expanded controls whether the
lowercase of the matched string should be used for the
substitution. Setting it as non-nil is useful to
avoid the creation of multiple groups when users send to an
address using different case (i.e. mailing-list@domain vs
Mailing-List@Domain). The default value is t.
nnmail-split-fancy-with-parent
is a function which allows you to split followups into the same
groups their parents are in. Sometimes you can't make splitting
rules for all your mail. For example, your boss might send you
personal mail regarding different projects you are working on,
and as you can't tell your boss to put a distinguishing string
into the subject line, you have to resort to manually moving the
messages into the right group. With this function, you only have
to do it once per thread.
To use this feature, you have to set
nnmail-treat-duplicates and
nnmail-cache-accepted-message-ids to a
non-nil value. And then you can include
nnmail-split-fancy-with-parent using the colon
feature, like so:
(setq nnmail-treat-duplicates 'warn ; or delete
nnmail-cache-accepted-message-ids t
nnmail-split-fancy
'(| (: nnmail-split-fancy-with-parent)
;; other splits go here
))
This feature works as follows: when
nnmail-treat-duplicates is non-nil,
Gnus records the message id of every message it sees in the file
specified by the variable
nnmail-message-id-cache-file, together with the
group it is in (the group is omitted for non-mail messages). When
mail splitting is invoked, the function
nnmail-split-fancy-with-parent then looks at the
References (and In-Reply-To) header of each message to split and
searches the file specified by
nnmail-message-id-cache-file for the message ids.
When it has found a parent, it returns the corresponding group
name unless the group name matches the regexp
nnmail-split-fancy-with-parent-ignore-groups. It is
recommended that you set
nnmail-message-id-cache-length to a somewhat higher
number than the default so that the message ids are still in the
cache. (A value of 5000 appears to create a file some 300 kBytes
in size.)
When nnmail-cache-accepted-message-ids is
non-nil, Gnus also records the message ids of moved
articles, so that the followup messages goes into the new
group.
Also see the variable nnmail-cache-ignore-groups
if you don't want certain groups to be recorded in the cache. For
example, if all outgoing messages are written to an
“outgoing” group, you could set
nnmail-cache-ignore-groups to match that group name.
Otherwise, answers to all your messages would end up in the
“outgoing” group.